package com.liuceng.zen.service;

import com.github.miemiedev.mybatis.paginator.domain.Order;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
import com.liuceng.zen.Page;
import com.liuceng.zen.constants.Constants;
import com.liuceng.zen.mapper.BaseMapper;
import com.liuceng.zen.pojo.domain.BaseDomain;
import com.liuceng.zen.pojo.form.*;
import com.liuceng.zen.web.Pageable;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

public abstract class BaseService<T extends BaseDomain> {
  public static final String DIRECT_EXCHANGE = "hlt.direct.exchange";
  protected static final Logger LOG = LoggerFactory.getLogger(BaseService.class);
  @Autowired
  private BaseMapper<T> baseMapper;

  @Transactional(readOnly = true)
  public T find(Integer id) {
    return baseMapper.selectByPrimaryKey(id);
  }

  @Transactional(readOnly = true)
  public T findOneByParams(Map<String, Object> params) {
    return baseMapper.findOneByParams(params);
  }

  @Transactional
  public Integer insert(T t) {
    t.setCreatedAt(new Date());
    t.setUpdatedAt(new Date());
    return baseMapper.insertSelective(t);
  }

  @Transactional
  public Integer update(T t) {
    t.setUpdatedAt(new Date());
    return baseMapper.updateByPrimaryKeySelective(t);
  }

  @Transactional
  public Integer delete(Integer id) {
    return baseMapper.deleteByPrimaryKey(id);
  }

  @Transactional
  public void batchInsert(List<T> records) {
    if (records != null && !records.isEmpty()) {
      List<T> newRecords = new ArrayList<>();
      newRecords = records.stream().map(record -> {
        record.setCreatedAt(new Date());
        record.setUpdatedAt(new Date());
        record.setVersion(0);
        return record;
      }).collect(Collectors.toList());
      //
      int pageSize = Constants.PAGE_SIZE;
      int totalSize = newRecords.size();
      int pages = (totalSize + pageSize - 1) / pageSize;
      LOG.info(">>>>>>>>>>>>>>>> batch insert begin ,total " + totalSize);
      //
      for (int currentPage = 1; currentPage <= pages; currentPage++) {
        int fromIdx = (currentPage - 1) * pageSize;
        int num = currentPage * pageSize > totalSize ? totalSize : (currentPage * pageSize);
        LOG.info("currentPage " + currentPage + " from " + fromIdx + " get " + num + " elms");
        baseMapper.batchInsert(newRecords.subList(fromIdx, num));
      }
      LOG.info("<<<<<<<<<<<<<<<< batch insert end");

    }
  }

  public List<T> search(Map<String, Object> params) {
    return baseMapper.search(params);
  }

  /**
   * 查找实体对象分页
   * 
   * @param tableForm 分页信息
   * @return 实体对象分页
   */
  @Transactional(readOnly = true)
  public Page<T> findPage(BaseTableForm tableForm) {

    Map<String, Object> filteMap = new HashMap();
    /*
     * if (!tableForm.getsSearch_0().equals("") && !tableForm.getsSearch_1().trim().equals("")) {
     * filteMap.put("searchProperty", tableForm.getsSearch_0()); filteMap.put("searchValue",
     * tableForm.getsSearch_1().trim()); }
     */
    // if (tableForm.getsSearch_2() != null && !tableForm.getsSearch_2().trim().equals("")) {
    // filteMap.put("startTime", tableForm.getDate(tableForm.getsSearch_2().trim() + " 00:00:00"));
    // filteMap.put("endTime", tableForm.getDate(tableForm.getsSearch_2().trim() + " 23:59:59"));
    // }
    // filteMap.put("startTime", tableForm.getsSearch_0());
    // filteMap.put("endTime", tableForm.getsSearch_1());
    // if (tableForm.getsSearch_0() != null && tableForm.getsSearch_1() != null) {
    // filteMap.put("startTime", tableForm.getsSearch_0());
    // filteMap.put("endTime", tableForm.getsSearch_1());
    // }
    if (tableForm.getsSearch_1() != null && !tableForm.getsSearch_1().trim().equals("")) {
      filteMap.put("startTime", tableForm.getDate(tableForm.getsSearch_1().trim() + " 00:00:00"));
    }
    if (tableForm.getsSearch_2() != null && !tableForm.getsSearch_2().trim().equals("")) {
      filteMap.put("endTime", tableForm.getDate(tableForm.getsSearch_2().trim() + " 23:59:59"));
    }
    // 快捷查询状态
    if (tableForm.getsSearch_3() != null && !tableForm.getsSearch_3().trim().equals("")
        && tableForm.getsSearch_4().trim().equals("radio")) {
      SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
      Calendar now = Calendar.getInstance();
      now.setTime(new Date());
      if (tableForm.getsSearch_3().trim().equals("seven")) {// 最近七天
        now.set(Calendar.DATE, now.get(Calendar.DATE) - 7);
        filteMap.put("startTime", tableForm.getDate(format.format(now.getTime()) + " 00:00:00"));
        filteMap.put("endTime", tableForm.getDate(format.format(new Date()) + " 23:59:59"));
      }
      if (tableForm.getsSearch_3().trim().equals("thirty")) {// 最近三十天
        now.set(Calendar.DATE, now.get(Calendar.DATE) - 30);
        filteMap.put("startTime", tableForm.getDate(format.format(now.getTime()) + " 00:00:00"));
        filteMap.put("endTime", tableForm.getDate(format.format(new Date()) + " 23:59:59"));
      }
    }
    // 判断是否有手机号、姓名查询
    if (tableForm.getsSearch_5() != null && !tableForm.getsSearch_5().trim().equals("")) {// 姓名
      filteMap.put("value1", tableForm.getsSearch_5().trim());
    }
    if (tableForm.getsSearch_0() != null && !tableForm.getsSearch_0().trim().equals("")) {// 手机号
      filteMap.put("value2", tableForm.getsSearch_0().trim());
    }

    if (tableForm instanceof MemberAccountFlowForm) {
      MemberAccountFlowForm memberAccountFlow = (MemberAccountFlowForm) tableForm;
      filteMap.put("memberId", memberAccountFlow.getMemberId());
    }
    if (tableForm instanceof MikeFormDataForm) {
      MikeFormDataForm mikeFormDataForm = (MikeFormDataForm) tableForm;
      filteMap.put("memberId", mikeFormDataForm.getMemberId());
    }
    if (tableForm instanceof GroupNotThroughReasonFrom) {
      GroupNotThroughReasonFrom reasonFrom = (GroupNotThroughReasonFrom) tableForm;
      filteMap.put("memberId", reasonFrom.getMemberId());
    }
    List<Order> orders =
        Arrays.asList(Order.create(tableForm.getmDataProp(), tableForm.getSortInfo().trim()));

    PageBounds pb =
        new PageBounds(tableForm.getiDisplayStart() / tableForm.getiDisplayLength() + 1,
            tableForm.getiDisplayLength(), orders);
    return this.search(filteMap, pb);
  }

  @Transactional(readOnly = true)
  public Page<T> search(Map<String, Object> params, PageBounds pb) {
    List<T> rpts = baseMapper.search(params, pb);
    PageList<T> pl = (PageList<T>) rpts;
    Integer totalCount = pl.getPaginator().getTotalCount();
    return new Page<T>(rpts, totalCount);
  }


  public List<T> searchWithoutCount(Map<String, Object> params, PageBounds pb) {
    List<T> rpts = baseMapper.search(params, pb);
    return rpts;
  }

  public int count(Map<String, Object> params) {
    return baseMapper.count(params);
  }

  /**
   * 分页组件
   * 
   * @param pageable
   * @return
   */
  public com.liuceng.zen.web.Page<T> findPage(Pageable pageable) {
    String orderProperty = pageable.getSort();
    List<Order> orders = new ArrayList<>();
    if (StringUtils.isNoneBlank(orderProperty)) {
      String order = pageable.getOrder();
      Order o = null;
      if (StringUtils.isNotBlank(order)) {
        String processedOrder = order.trim().toLowerCase();
        if (!"desc".equals(processedOrder)) {
          processedOrder = "asc";
        }
        //
        o = Order.create(orderProperty, processedOrder);
      } else {
        o = Order.create(orderProperty, "asc");
      }
      orders.add(o);
    }
    // 权限
    Map<String, Object> filterMap = new HashMap<>();
    filterMap.put("stratTime", pageable.getStartTime());
    filterMap.put("endTime", pageable.getEndTime());
    filterMap.put("searchName", pageable.getSearchName());
    filterMap.put("searchValue", pageable.getSearchValue());
    filterMap.put("showType", pageable.getShowType());
    filterMap.put("memberId", pageable.getMemberId());
    PageBounds pageBounds = new PageBounds(pageable.getOffset(), pageable.getLimit(), orders, true);
    List<T> records = baseMapper.search(filterMap, pageBounds);
    PageList<T> pl = (PageList<T>) records;
    Integer totalCount = pl.getPaginator().getTotalCount();

    return new com.liuceng.zen.web.Page<T>(records, totalCount, pageable);
  }

  /**
   * 分页查询
   */

  public Page<T> findPage(BaseForm baseForm) {
    // 分页PageBounds
    PageBounds pb = baseForm.getPageBounds();
    Map<String, Object> filterMap = baseForm.getFilterMap();
    // 搜索条件
    filterMap.put("searchProperty", baseForm.getSearchProperty());
    filterMap.put("searchValue", baseForm.getSearchValue());
    if (baseForm.getCrtSize() != null && baseForm.getCrtSize() != 0) {
      filterMap.put("crtSize", baseForm.getCrtSize());
    }
    if (baseForm.getCrtSizeMediumMenuId() != null && baseForm.getCrtSizeMediumMenuId() != 0) {
      filterMap.put("crtSizeMediumMenuId", baseForm.getCrtSizeMediumMenuId());
    }
    if (baseForm.getMemberId() != null) {
      filterMap.put("memberId", baseForm.getMemberId());
    }
    if (baseForm.getSitesetType() != null) {
      filterMap.put("sitesetType", baseForm.getSitesetType());
    }
    if (baseForm.getShowType() != null) {
      filterMap.put("showType", baseForm.getShowType());
    }
    // 排序
    String orderProperty = baseForm.getOrderProperty();
    if (StringUtils.isNoneBlank(orderProperty)) {
      String order = baseForm.getOrderDirection();
      Order o = null;
      if (StringUtils.isNotBlank(order)) {
        String processedOrder = order.trim().toLowerCase();
        if (!"desc".equals(processedOrder)) {
          processedOrder = "asc";
        }
        o = Order.create(orderProperty, processedOrder);
      } else {
        o = Order.create(orderProperty, "asc");
      }
      List<Order> orders = Arrays.asList(o);
      pb.setOrders(orders);
    }
    return this.search(filterMap, pb, baseForm);
  }

  @Transactional(readOnly = true)
  public Page<T> search(Map<String, Object> params, PageBounds pb, BaseForm baseForm) {
    List<T> rpts = baseMapper.search(params, pb);
    PageList<T> pl = (PageList<T>) rpts;
    Integer totalCount = pl.getPaginator().getTotalCount();
    return new Page<T>(rpts, totalCount, baseForm);
  }
}
